﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GLWrap.MathExt;
using System.Diagnostics;
using Sharp3D.Math.Core;
using GLWrap.SceneObjects.Line;

namespace GLWrap.SceneObjects
{
	public class DoubleLine: BaseLine
	{
        private const float DEFAULT_DISTANCE = 0.1f;
        private const float DEFAULT_WEIGHT = 0.01f;

        private float _distance;
        private BaseLine _line1;
        private BaseLine _line2;

        public override float Weight
        {
            get
            {
                return _weight;
            }
            set
            {
                _weight = value;
                _line1.Weight = value;
                _line2.Weight = value;
            }
        }

        public float Distance
        {
            get
            {
                return _distance;
            }
            set
            {
                _distance = value;
                MarkAsDirty();
            }
        }

        public BaseLine Line1 { get { return _line1; } }
        public BaseLine Line2 { get { return _line2; } }

        public  DoubleLine():this(new SimpleLine(),new SimpleLine()) {}

        public DoubleLine(BaseLine line1, BaseLine line2)
        {
            if (line1 == null) throw new ArgumentNullException("line1");
            if (line2 == null) throw new ArgumentNullException("line2");

            PointA = new Vector3F(0, 0, 0);
            PointB = new Vector3F(0, -1, -1);
            _distance = DEFAULT_DISTANCE;

            _line1 = line1;
            _line2 = line2;

            AttachObject(_line1);
            AttachObject(_line2);
        }

        protected override void InternalRecalculateLineForSceneManager(GlSceneManager sceneManager)
        {
            Vector3F lookVector = sceneManager.Camera.View - sceneManager.Camera.Eye;

            Vector3F lineVector = PointA - PointB;

            Vector3F inPlaneShiftVector = Vector3F.CrossProduct(lookVector, lineVector);

            inPlaneShiftVector.Normalize();

            inPlaneShiftVector = inPlaneShiftVector * _distance;

            _line1.PointB = new Vector3F(PointB + inPlaneShiftVector);
            _line1.PointA = new Vector3F(_line1.PointB + lineVector);

            _line2.PointB = new Vector3F(PointB - inPlaneShiftVector);
            _line2.PointA = new Vector3F(_line2.PointB + lineVector);
        }

        protected override void InternalLineAttachedToScene(GlSceneManager sceneManager)
        {
            sceneManager.Camera.CameraPositionChanged += Camera_CameraPositionChanged;
        }

        protected override void InternalLineDetachedFromScene(GlSceneManager sceneManager)
        {
            sceneManager.Camera.CameraPositionChanged -= Camera_CameraPositionChanged; ;
        }

        private void Camera_CameraPositionChanged(object sender, EventArgs e)
        {
            MarkAsDirty();
        }
	}
}
